Skip to content

Commit

Permalink
feat: fake-ip-filter support rule-set: and geosite:
Browse files Browse the repository at this point in the history
  • Loading branch information
wwqgtxx committed Aug 14, 2024
1 parent f20f371 commit 696b75e
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 10 deletions.
19 changes: 16 additions & 3 deletions component/fakeip/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/metacubex/mihomo/common/nnip"
"github.com/metacubex/mihomo/component/profile/cachefile"
"github.com/metacubex/mihomo/component/trie"
C "github.com/metacubex/mihomo/constant"
)

const (
Expand Down Expand Up @@ -36,6 +37,7 @@ type Pool struct {
cycle bool
mux sync.Mutex
host *trie.DomainTrie[struct{}]
rules []C.Rule
ipnet netip.Prefix
store store
}
Expand Down Expand Up @@ -66,10 +68,18 @@ func (p *Pool) LookBack(ip netip.Addr) (string, bool) {

// ShouldSkipped return if domain should be skipped
func (p *Pool) ShouldSkipped(domain string) bool {
if p.host == nil {
return false
if p.host != nil {
if p.host.Search(domain) != nil {
return true
}
}
for _, rule := range p.rules {
metadata := &C.Metadata{Host: domain}
if match, _ := rule.Match(metadata); match {
return true
}
}
return p.host.Search(domain) != nil
return false
}

// Exist returns if given ip exists in fake-ip pool
Expand Down Expand Up @@ -156,6 +166,8 @@ type Options struct {
IPNet netip.Prefix
Host *trie.DomainTrie[struct{}]

Rules []C.Rule

// Size sets the maximum number of entries in memory
// and does not work if Persistence is true
Size int
Expand Down Expand Up @@ -185,6 +197,7 @@ func New(options Options) (*Pool, error) {
offset: first.Prev(),
cycle: false,
host: options.Host,
rules: options.Rules,
ipnet: options.IPNet,
}
if options.Persistence {
Expand Down
59 changes: 57 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/log"
R "github.com/metacubex/mihomo/rules"
RC "github.com/metacubex/mihomo/rules/common"
RP "github.com/metacubex/mihomo/rules/provider"
T "github.com/metacubex/mihomo/tunnel"

Expand Down Expand Up @@ -1408,13 +1409,63 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
}

var host *trie.DomainTrie[struct{}]
var fakeIPRules []C.Rule
// fake ip skip host filter
if len(cfg.FakeIPFilter) != 0 {
host = trie.New[struct{}]()
for _, domain := range cfg.FakeIPFilter {
_ = host.Insert(domain, struct{}{})
if strings.Contains(strings.ToLower(domain), ",") {
if strings.Contains(domain, "geosite:") {
subkeys := strings.Split(domain, ":")
subkeys = subkeys[1:]
subkeys = strings.Split(subkeys[0], ",")
for _, country := range subkeys {
found := false
for _, rule := range rules {
if rule.RuleType() == C.GEOSITE {
if strings.EqualFold(country, rule.Payload()) {
found = true
fakeIPRules = append(fakeIPRules, rule)
}
}
}
if !found {
rule, err := RC.NewGEOSITE(country, "")
if err != nil {
return nil, err
}
fakeIPRules = append(fakeIPRules, rule)
}
}

}
} else if strings.Contains(strings.ToLower(domain), "rule-set:") {
subkeys := strings.Split(domain, ":")
subkeys = subkeys[1:]
subkeys = strings.Split(subkeys[0], ",")
for _, domainSetName := range subkeys {
if rp, ok := ruleProviders[domainSetName]; !ok {
return nil, fmt.Errorf("not found rule-set: %s", domainSetName)
} else {
switch rp.Behavior() {
case providerTypes.IPCIDR:
return nil, fmt.Errorf("rule provider type error, except domain,actual %s", rp.Behavior())
case providerTypes.Classical:
log.Warnln("%s provider is %s, only matching it contain domain rule", rp.Name(), rp.Behavior())
default:
}
}
rule, err := RP.NewRuleSet(domainSetName, "", true)
if err != nil {
return nil, err
}

fakeIPRules = append(fakeIPRules, rule)
}
} else {
_ = host.Insert(domain, struct{}{})
}
}
host.Optimize()
}

if len(dnsCfg.Fallback) != 0 {
Expand All @@ -1427,13 +1478,17 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
}
_ = host.Insert(fb.Addr, struct{}{})
}
}

if host != nil {
host.Optimize()
}

pool, err := fakeip.New(fakeip.Options{
IPNet: fakeIPRange,
Size: 1000,
Host: host,
Rules: fakeIPRules,
Persistence: rawCfg.Profile.StoreFakeIP,
})
if err != nil {
Expand Down
15 changes: 10 additions & 5 deletions docs/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,16 @@ dns:

fake-ip-range: 198.18.0.1/16 # fake-ip 池设置

# 配置不使用 fake-ip 的域名
fake-ip-filter:
- '*.lan'
- localhost.ptlogin2.qq.com
# fakeip-filter 为 rule-providers 中的名为 fakeip-filter 规则订阅,
# 且 behavior 必须为 domain/classical,当为 classical 时仅会生效域名类规则
- rule-set:fakeip-filter
# fakeip-filter 为 geosite 中名为 fakeip-filter 的分类(需要自行保证该分类存在)
- geosite:fakeip-filter

# use-hosts: true # 查询 hosts

# 配置后面的nameserver、fallback和nameserver-policy向dns服务器的连接过程是否遵守遵守rules规则
Expand All @@ -252,11 +262,6 @@ dns:
# 此外,这三者配置中的dns服务器如果出现域名会采用default-nameserver配置项解析,也请确保正确配置default-nameserver
respect-rules: false

# 配置不使用 fake-ip 的域名
# fake-ip-filter:
# - '*.lan'
# - localhost.ptlogin2.qq.com

# DNS 主要域名配置
# 支持 UDP,TCP,DoT,DoH,DoQ
# 这部分为主要 DNS 配置,影响所有直连,确保使用对大陆解析精准的 DNS
Expand Down

0 comments on commit 696b75e

Please sign in to comment.