mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-11-16 11:42:43 +08:00
feat: fake-ip-filter
support rule-set:
and geosite:
This commit is contained in:
parent
f20f371a61
commit
696b75ee37
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/metacubex/mihomo/common/nnip"
|
"github.com/metacubex/mihomo/common/nnip"
|
||||||
"github.com/metacubex/mihomo/component/profile/cachefile"
|
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||||
"github.com/metacubex/mihomo/component/trie"
|
"github.com/metacubex/mihomo/component/trie"
|
||||||
|
C "github.com/metacubex/mihomo/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -36,6 +37,7 @@ type Pool struct {
|
||||||
cycle bool
|
cycle bool
|
||||||
mux sync.Mutex
|
mux sync.Mutex
|
||||||
host *trie.DomainTrie[struct{}]
|
host *trie.DomainTrie[struct{}]
|
||||||
|
rules []C.Rule
|
||||||
ipnet netip.Prefix
|
ipnet netip.Prefix
|
||||||
store store
|
store store
|
||||||
}
|
}
|
||||||
|
@ -66,10 +68,18 @@ func (p *Pool) LookBack(ip netip.Addr) (string, bool) {
|
||||||
|
|
||||||
// ShouldSkipped return if domain should be skipped
|
// ShouldSkipped return if domain should be skipped
|
||||||
func (p *Pool) ShouldSkipped(domain string) bool {
|
func (p *Pool) ShouldSkipped(domain string) bool {
|
||||||
if p.host == nil {
|
if p.host != nil {
|
||||||
return false
|
if p.host.Search(domain) != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return p.host.Search(domain) != nil
|
for _, rule := range p.rules {
|
||||||
|
metadata := &C.Metadata{Host: domain}
|
||||||
|
if match, _ := rule.Match(metadata); match {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist returns if given ip exists in fake-ip pool
|
// Exist returns if given ip exists in fake-ip pool
|
||||||
|
@ -156,6 +166,8 @@ type Options struct {
|
||||||
IPNet netip.Prefix
|
IPNet netip.Prefix
|
||||||
Host *trie.DomainTrie[struct{}]
|
Host *trie.DomainTrie[struct{}]
|
||||||
|
|
||||||
|
Rules []C.Rule
|
||||||
|
|
||||||
// Size sets the maximum number of entries in memory
|
// Size sets the maximum number of entries in memory
|
||||||
// and does not work if Persistence is true
|
// and does not work if Persistence is true
|
||||||
Size int
|
Size int
|
||||||
|
@ -185,6 +197,7 @@ func New(options Options) (*Pool, error) {
|
||||||
offset: first.Prev(),
|
offset: first.Prev(),
|
||||||
cycle: false,
|
cycle: false,
|
||||||
host: options.Host,
|
host: options.Host,
|
||||||
|
rules: options.Rules,
|
||||||
ipnet: options.IPNet,
|
ipnet: options.IPNet,
|
||||||
}
|
}
|
||||||
if options.Persistence {
|
if options.Persistence {
|
||||||
|
|
|
@ -38,6 +38,7 @@ import (
|
||||||
LC "github.com/metacubex/mihomo/listener/config"
|
LC "github.com/metacubex/mihomo/listener/config"
|
||||||
"github.com/metacubex/mihomo/log"
|
"github.com/metacubex/mihomo/log"
|
||||||
R "github.com/metacubex/mihomo/rules"
|
R "github.com/metacubex/mihomo/rules"
|
||||||
|
RC "github.com/metacubex/mihomo/rules/common"
|
||||||
RP "github.com/metacubex/mihomo/rules/provider"
|
RP "github.com/metacubex/mihomo/rules/provider"
|
||||||
T "github.com/metacubex/mihomo/tunnel"
|
T "github.com/metacubex/mihomo/tunnel"
|
||||||
|
|
||||||
|
@ -1408,13 +1409,63 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
|
||||||
}
|
}
|
||||||
|
|
||||||
var host *trie.DomainTrie[struct{}]
|
var host *trie.DomainTrie[struct{}]
|
||||||
|
var fakeIPRules []C.Rule
|
||||||
// fake ip skip host filter
|
// fake ip skip host filter
|
||||||
if len(cfg.FakeIPFilter) != 0 {
|
if len(cfg.FakeIPFilter) != 0 {
|
||||||
host = trie.New[struct{}]()
|
host = trie.New[struct{}]()
|
||||||
for _, domain := range cfg.FakeIPFilter {
|
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 {
|
if len(dnsCfg.Fallback) != 0 {
|
||||||
|
@ -1427,6 +1478,9 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
|
||||||
}
|
}
|
||||||
_ = host.Insert(fb.Addr, struct{}{})
|
_ = host.Insert(fb.Addr, struct{}{})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if host != nil {
|
||||||
host.Optimize()
|
host.Optimize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1434,6 +1488,7 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
|
||||||
IPNet: fakeIPRange,
|
IPNet: fakeIPRange,
|
||||||
Size: 1000,
|
Size: 1000,
|
||||||
Host: host,
|
Host: host,
|
||||||
|
Rules: fakeIPRules,
|
||||||
Persistence: rawCfg.Profile.StoreFakeIP,
|
Persistence: rawCfg.Profile.StoreFakeIP,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -243,6 +243,16 @@ dns:
|
||||||
|
|
||||||
fake-ip-range: 198.18.0.1/16 # fake-ip 池设置
|
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
|
# use-hosts: true # 查询 hosts
|
||||||
|
|
||||||
# 配置后面的nameserver、fallback和nameserver-policy向dns服务器的连接过程是否遵守遵守rules规则
|
# 配置后面的nameserver、fallback和nameserver-policy向dns服务器的连接过程是否遵守遵守rules规则
|
||||||
|
@ -252,11 +262,6 @@ dns:
|
||||||
# 此外,这三者配置中的dns服务器如果出现域名会采用default-nameserver配置项解析,也请确保正确配置default-nameserver
|
# 此外,这三者配置中的dns服务器如果出现域名会采用default-nameserver配置项解析,也请确保正确配置default-nameserver
|
||||||
respect-rules: false
|
respect-rules: false
|
||||||
|
|
||||||
# 配置不使用 fake-ip 的域名
|
|
||||||
# fake-ip-filter:
|
|
||||||
# - '*.lan'
|
|
||||||
# - localhost.ptlogin2.qq.com
|
|
||||||
|
|
||||||
# DNS 主要域名配置
|
# DNS 主要域名配置
|
||||||
# 支持 UDP,TCP,DoT,DoH,DoQ
|
# 支持 UDP,TCP,DoT,DoH,DoQ
|
||||||
# 这部分为主要 DNS 配置,影响所有直连,确保使用对大陆解析精准的 DNS
|
# 这部分为主要 DNS 配置,影响所有直连,确保使用对大陆解析精准的 DNS
|
||||||
|
|
Loading…
Reference in New Issue
Block a user