chore: add sourceGeoIP and sourceIPASN to metadata

This commit is contained in:
wwqgtxx 2024-08-28 12:25:45 +08:00
parent 8483178524
commit 4fecf68b8b
17 changed files with 211 additions and 211 deletions

View File

@ -46,6 +46,14 @@ func (set *IpCidrSet) IsContain(ip netip.Addr) bool {
return set.ToIPSet().Contains(ip.WithZone(""))
}
// MatchIp implements C.IpMatcher
func (set *IpCidrSet) MatchIp(ip netip.Addr) bool {
if set.IsEmpty() {
return false
}
return set.IsContain(ip)
}
func (set *IpCidrSet) Merge() error {
var b netipx.IPSetBuilder
b.AddSet(set.ToIPSet())

View File

@ -35,7 +35,7 @@ type Pool struct {
offset netip.Addr
cycle bool
mux sync.Mutex
host []C.Rule
host []C.DomainMatcher
ipnet netip.Prefix
store store
}
@ -66,8 +66,8 @@ func (p *Pool) LookBack(ip netip.Addr) (string, bool) {
// ShouldSkipped return if domain should be skipped
func (p *Pool) ShouldSkipped(domain string) bool {
for _, rule := range p.host {
if match, _ := rule.Match(&C.Metadata{Host: domain}); match {
for _, matcher := range p.host {
if matcher.MatchDomain(domain) {
return true
}
}
@ -156,7 +156,7 @@ func (p *Pool) restoreState() {
type Options struct {
IPNet netip.Prefix
Host []C.Rule
Host []C.DomainMatcher
// Size sets the maximum number of entries in memory
// and does not work if Persistence is true

View File

@ -10,7 +10,6 @@ import (
"github.com/metacubex/mihomo/component/profile/cachefile"
"github.com/metacubex/mihomo/component/trie"
C "github.com/metacubex/mihomo/constant"
RP "github.com/metacubex/mihomo/rules/provider"
"github.com/metacubex/bbolt"
"github.com/stretchr/testify/assert"
@ -157,7 +156,7 @@ func TestPool_Skip(t *testing.T) {
pools, tempfile, err := createPools(Options{
IPNet: ipnet,
Size: 10,
Host: []C.Rule{RP.NewDomainSet(tree.NewDomainSet(), "")},
Host: []C.DomainMatcher{tree.NewDomainSet()},
})
assert.Nil(t, err)
defer os.Remove(tempfile)

View File

@ -22,23 +22,23 @@ var (
type Dispatcher struct {
enable bool
sniffers map[sniffer.Sniffer]SnifferConfig
forceDomain []C.Rule
skipSrcAddress []C.Rule
skipDstAddress []C.Rule
skipDomain []C.Rule
forceDomain []C.DomainMatcher
skipSrcAddress []C.IpMatcher
skipDstAddress []C.IpMatcher
skipDomain []C.DomainMatcher
skipList *lru.LruCache[netip.AddrPort, uint8]
forceDnsMapping bool
parsePureIp bool
}
func (sd *Dispatcher) shouldOverride(metadata *C.Metadata) bool {
for _, rule := range sd.skipDstAddress {
if ok, _ := rule.Match(&C.Metadata{DstIP: metadata.DstIP}); ok {
for _, matcher := range sd.skipDstAddress {
if matcher.MatchIp(metadata.DstIP) {
return false
}
}
for _, rule := range sd.skipSrcAddress {
if ok, _ := rule.Match(&C.Metadata{DstIP: metadata.SrcIP}); ok {
for _, matcher := range sd.skipSrcAddress {
if matcher.MatchIp(metadata.SrcIP) {
return false
}
}
@ -48,8 +48,8 @@ func (sd *Dispatcher) shouldOverride(metadata *C.Metadata) bool {
if metadata.DNSMode == C.DNSMapping && sd.forceDnsMapping {
return true
}
for _, rule := range sd.forceDomain {
if ok, _ := rule.Match(&C.Metadata{Host: metadata.Host}); ok {
for _, matcher := range sd.forceDomain {
if matcher.MatchDomain(metadata.Host) {
return true
}
}
@ -112,8 +112,8 @@ func (sd *Dispatcher) TCPSniff(conn *N.BufferedConn, metadata *C.Metadata) bool
return false
}
for _, rule := range sd.skipDomain {
if ok, _ := rule.Match(&C.Metadata{Host: host}); ok {
for _, matcher := range sd.skipDomain {
if matcher.MatchDomain(host) {
log.Debugln("[Sniffer] Skip sni[%s]", host)
return false
}
@ -200,10 +200,10 @@ func (sd *Dispatcher) cacheSniffFailed(metadata *C.Metadata) {
type Config struct {
Enable bool
Sniffers map[sniffer.Type]SnifferConfig
ForceDomain []C.Rule
SkipSrcAddress []C.Rule
SkipDstAddress []C.Rule
SkipDomain []C.Rule
ForceDomain []C.DomainMatcher
SkipSrcAddress []C.IpMatcher
SkipDstAddress []C.IpMatcher
SkipDomain []C.DomainMatcher
ForceDnsMapping bool
ParsePureIp bool
}

View File

@ -172,6 +172,11 @@ func (ss *DomainSet) Foreach(f func(key string) bool) {
})
}
// MatchDomain implements C.DomainMatcher
func (ss *DomainSet) MatchDomain(domain string) bool {
return ss.Has(domain)
}
func setBit(bm *[]uint64, i int, v int) {
for i>>6 >= len(*bm) {
*bm = append(*bm, 0)

View File

@ -143,8 +143,8 @@ type DNS struct {
UseSystemHosts bool
NameServer []dns.NameServer
Fallback []dns.NameServer
FallbackIPFilter []C.Rule
FallbackDomainFilter []C.Rule
FallbackIPFilter []C.IpMatcher
FallbackDomainFilter []C.DomainMatcher
Listen string
EnhancedMode C.DNSMode
DefaultNameserver []dns.NameServer
@ -640,7 +640,7 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
}
config.Hosts = hosts
dnsCfg, err := parseDNS(rawCfg, hosts, rules, ruleProviders)
dnsCfg, err := parseDNS(rawCfg, hosts, ruleProviders)
if err != nil {
return nil, err
}
@ -1297,7 +1297,7 @@ func parsePureDNSServer(server string) string {
}
}
func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], rules []C.Rule, ruleProviders map[string]providerTypes.RuleProvider, respectRules bool, preferH3 bool) ([]dns.Policy, error) {
func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], ruleProviders map[string]providerTypes.RuleProvider, respectRules bool, preferH3 bool) ([]dns.Policy, error) {
var policy []dns.Policy
re := regexp.MustCompile(`[a-zA-Z0-9\-]+\.[a-zA-Z]{2,}(\.[a-zA-Z]{2,})?`)
@ -1350,18 +1350,18 @@ func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], rules [
if strings.HasPrefix(domain, "rule-set:") {
domainSetName := domain[9:]
rule, err := parseDomainRuleSet(domainSetName, "dns.nameserver-policy", ruleProviders)
matcher, err := parseDomainRuleSet(domainSetName, "dns.nameserver-policy", ruleProviders)
if err != nil {
return nil, err
}
policy[idx] = dns.Policy{Rule: rule, NameServers: nameservers}
policy[idx] = dns.Policy{Matcher: matcher, NameServers: nameservers}
} else if strings.HasPrefix(domain, "geosite:") {
country := domain[8:]
rule, err := RC.NewGEOSITE(country, "dns.nameserver-policy")
matcher, err := RC.NewGEOSITE(country, "dns.nameserver-policy")
if err != nil {
return nil, err
}
policy[idx] = dns.Policy{Rule: rule, NameServers: nameservers}
policy[idx] = dns.Policy{Matcher: matcher, NameServers: nameservers}
} else {
if _, valid := trie.ValidAndSplitDomain(domain); !valid {
return nil, fmt.Errorf("DNS ResoverRule invalid domain: %s", domain)
@ -1372,7 +1372,7 @@ func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], rules [
return policy, nil
}
func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rules []C.Rule, ruleProviders map[string]providerTypes.RuleProvider) (*DNS, error) {
func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], ruleProviders map[string]providerTypes.RuleProvider) (*DNS, error) {
cfg := rawCfg.DNS
if cfg.Enable && len(cfg.NameServer) == 0 {
return nil, fmt.Errorf("if DNS configuration is turned on, NameServer cannot be empty")
@ -1400,7 +1400,7 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
return nil, err
}
if dnsCfg.NameServerPolicy, err = parseNameServerPolicy(cfg.NameServerPolicy, rules, ruleProviders, cfg.RespectRules, cfg.PreferH3); err != nil {
if dnsCfg.NameServerPolicy, err = parseNameServerPolicy(cfg.NameServerPolicy, ruleProviders, cfg.RespectRules, cfg.PreferH3); err != nil {
return nil, err
}
@ -1467,14 +1467,13 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
dnsCfg.FakeIPRange = pool
}
var rule C.Rule
if len(cfg.Fallback) != 0 {
if cfg.FallbackFilter.GeoIP {
rule, err = RC.NewGEOIP(cfg.FallbackFilter.GeoIPCode, "dns.fallback-filter.geoip", false, true)
matcher, err := RC.NewGEOIP(cfg.FallbackFilter.GeoIPCode, "dns.fallback-filter.geoip", false, true)
if err != nil {
return nil, fmt.Errorf("load GeoIP dns fallback filter error, %w", err)
}
dnsCfg.FallbackIPFilter = append(dnsCfg.FallbackIPFilter, rule)
dnsCfg.FallbackIPFilter = append(dnsCfg.FallbackIPFilter, matcher)
}
if len(cfg.FallbackFilter.IPCIDR) > 0 {
cidrSet := cidr.NewIpCidrSet()
@ -1488,8 +1487,8 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
if err != nil {
return nil, err
}
rule = RP.NewIpCidrSet(cidrSet, "dns.fallback-filter.ipcidr")
dnsCfg.FallbackIPFilter = append(dnsCfg.FallbackIPFilter, rule)
matcher := cidrSet // dns.fallback-filter.ipcidr
dnsCfg.FallbackIPFilter = append(dnsCfg.FallbackIPFilter, matcher)
}
if len(cfg.FallbackFilter.Domain) > 0 {
domainTrie := trie.New[struct{}]()
@ -1499,17 +1498,17 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
return nil, fmt.Errorf("DNS FallbackDomain[%d] format error: %w", idx, err)
}
}
rule = RP.NewDomainSet(domainTrie.NewDomainSet(), "dns.fallback-filter.domain")
dnsCfg.FallbackDomainFilter = append(dnsCfg.FallbackDomainFilter, rule)
matcher := domainTrie.NewDomainSet() // dns.fallback-filter.domain
dnsCfg.FallbackDomainFilter = append(dnsCfg.FallbackDomainFilter, matcher)
}
if len(cfg.FallbackFilter.GeoSite) > 0 {
log.Warnln("replace fallback-filter.geosite with nameserver-policy, it will be removed in the future")
for idx, geoSite := range cfg.FallbackFilter.GeoSite {
rule, err = RC.NewGEOSITE(geoSite, "dns.fallback-filter.geosite")
matcher, err := RC.NewGEOSITE(geoSite, "dns.fallback-filter.geosite")
if err != nil {
return nil, fmt.Errorf("DNS FallbackGeosite[%d] format error: %w", idx, err)
}
dnsCfg.FallbackDomainFilter = append(dnsCfg.FallbackDomainFilter, rule)
dnsCfg.FallbackDomainFilter = append(dnsCfg.FallbackDomainFilter, matcher)
}
}
}
@ -1701,8 +1700,8 @@ func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.
return snifferConfig, nil
}
func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (ipRules []C.Rule, err error) {
var rule C.Rule
func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (matchers []C.IpMatcher, err error) {
var matcher C.IpMatcher
for _, ipcidr := range addresses {
ipcidrLower := strings.ToLower(ipcidr)
if strings.Contains(ipcidrLower, "geoip:") {
@ -1710,22 +1709,22 @@ func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string
subkeys = subkeys[1:]
subkeys = strings.Split(subkeys[0], ",")
for _, country := range subkeys {
rule, err = RC.NewGEOIP(country, adapterName, false, false)
matcher, err = RC.NewGEOIP(country, adapterName, false, false)
if err != nil {
return nil, err
}
ipRules = append(ipRules, rule)
matchers = append(matchers, matcher)
}
} else if strings.Contains(ipcidrLower, "rule-set:") {
subkeys := strings.Split(ipcidr, ":")
subkeys = subkeys[1:]
subkeys = strings.Split(subkeys[0], ",")
for _, domainSetName := range subkeys {
rule, err = parseIPRuleSet(domainSetName, adapterName, ruleProviders)
matcher, err = parseIPRuleSet(domainSetName, adapterName, ruleProviders)
if err != nil {
return nil, err
}
ipRules = append(ipRules, rule)
matchers = append(matchers, matcher)
}
} else {
if cidrSet == nil {
@ -1742,14 +1741,14 @@ func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string
if err != nil {
return nil, err
}
rule = RP.NewIpCidrSet(cidrSet, adapterName)
ipRules = append(ipRules, rule)
matcher = cidrSet
matchers = append(matchers, matcher)
}
return
}
func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (domainRules []C.Rule, err error) {
var rule C.Rule
func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (matchers []C.DomainMatcher, err error) {
var matcher C.DomainMatcher
for _, domain := range domains {
domainLower := strings.ToLower(domain)
if strings.Contains(domainLower, "geosite:") {
@ -1757,22 +1756,22 @@ func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapte
subkeys = subkeys[1:]
subkeys = strings.Split(subkeys[0], ",")
for _, country := range subkeys {
rule, err = RC.NewGEOSITE(country, adapterName)
matcher, err = RC.NewGEOSITE(country, adapterName)
if err != nil {
return nil, err
}
domainRules = append(domainRules, rule)
matchers = append(matchers, matcher)
}
} else if strings.Contains(domainLower, "rule-set:") {
subkeys := strings.Split(domain, ":")
subkeys = subkeys[1:]
subkeys = strings.Split(subkeys[0], ",")
for _, domainSetName := range subkeys {
rule, err = parseDomainRuleSet(domainSetName, adapterName, ruleProviders)
matcher, err = parseDomainRuleSet(domainSetName, adapterName, ruleProviders)
if err != nil {
return nil, err
}
domainRules = append(domainRules, rule)
matchers = append(matchers, matcher)
}
} else {
if domainTrie == nil {
@ -1785,13 +1784,13 @@ func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapte
}
}
if !domainTrie.IsEmpty() {
rule = RP.NewDomainSet(domainTrie.NewDomainSet(), adapterName)
domainRules = append(domainRules, rule)
matcher = domainTrie.NewDomainSet()
matchers = append(matchers, matcher)
}
return
}
func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.Rule, error) {
func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.IpMatcher, error) {
if rp, ok := ruleProviders[domainSetName]; !ok {
return nil, fmt.Errorf("not found rule-set: %s", domainSetName)
} else {
@ -1806,7 +1805,7 @@ func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[
return RP.NewRuleSet(domainSetName, adapterName, true)
}
func parseDomainRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.Rule, error) {
func parseDomainRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.DomainMatcher, error) {
if rp, ok := ruleProviders[domainSetName]; !ok {
return nil, fmt.Errorf("not found rule-set: %s", domainSetName)
} else {

11
constant/matcher.go Normal file
View File

@ -0,0 +1,11 @@
package constant
import "net/netip"
type DomainMatcher interface {
MatchDomain(domain string) bool
}
type IpMatcher interface {
MatchIp(ip netip.Addr) bool
}

View File

@ -133,7 +133,9 @@ type Metadata struct {
Type Type `json:"type"`
SrcIP netip.Addr `json:"sourceIP"`
DstIP netip.Addr `json:"destinationIP"`
SrcGeoIP []string `json:"sourceGeoIP"` // can be nil if never queried, empty slice if got no result
DstGeoIP []string `json:"destinationGeoIP"` // can be nil if never queried, empty slice if got no result
SrcIPASN string `json:"sourceIPASN"`
DstIPASN string `json:"destinationIPASN"`
SrcPort uint16 `json:"sourcePort,string"` // `,string` is used to compatible with old version json output
DstPort uint16 `json:"destinationPort,string"` // `,string` is used to compatible with old version json output

View File

@ -27,8 +27,6 @@ const (
ProcessNameRegex
ProcessPathRegex
RuleSet
DomainSet
IpCidrSet
Network
Uid
SubRules
@ -92,10 +90,6 @@ func (rt RuleType) String() string {
return "Match"
case RuleSet:
return "RuleSet"
case DomainSet:
return "DomainSet"
case IpCidrSet:
return "IpCidrSet"
case Network:
return "Network"
case DSCP:

View File

@ -21,13 +21,13 @@ func (p domainTriePolicy) Match(domain string) []dnsClient {
return nil
}
type domainRulePolicy struct {
rule C.Rule
type domainMatcherPolicy struct {
matcher C.DomainMatcher
dnsClients []dnsClient
}
func (p domainRulePolicy) Match(domain string) []dnsClient {
if ok, _ := p.rule.Match(&C.Metadata{Host: domain}); ok {
func (p domainMatcherPolicy) Match(domain string) []dnsClient {
if p.matcher.MatchDomain(domain) {
return p.dnsClients
}
return nil

View File

@ -42,8 +42,8 @@ type Resolver struct {
hosts *trie.DomainTrie[resolver.HostValue]
main []dnsClient
fallback []dnsClient
fallbackDomainFilters []C.Rule
fallbackIPFilters []C.Rule
fallbackDomainFilters []C.DomainMatcher
fallbackIPFilters []C.IpMatcher
group singleflight.Group[*D.Msg]
cache dnsCache
policy []dnsPolicy
@ -119,7 +119,7 @@ func (r *Resolver) LookupIPv6(ctx context.Context, host string) ([]netip.Addr, e
func (r *Resolver) shouldIPFallback(ip netip.Addr) bool {
for _, filter := range r.fallbackIPFilters {
if ok, _ := filter.Match(&C.Metadata{DstIP: ip}); ok {
if filter.MatchIp(ip) {
return true
}
}
@ -275,7 +275,7 @@ func (r *Resolver) shouldOnlyQueryFallback(m *D.Msg) bool {
}
for _, df := range r.fallbackDomainFilters {
if ok, _ := df.Match(&C.Metadata{Host: domain}); ok {
if df.MatchDomain(domain) {
return true
}
}
@ -398,7 +398,7 @@ func (ns NameServer) Equal(ns2 NameServer) bool {
type Policy struct {
Domain string
Rule C.Rule
Matcher C.DomainMatcher
NameServers []NameServer
}
@ -409,8 +409,8 @@ type Config struct {
IPv6 bool
IPv6Timeout uint
EnhancedMode C.DNSMode
FallbackIPFilter []C.Rule
FallbackDomainFilter []C.Rule
FallbackIPFilter []C.IpMatcher
FallbackDomainFilter []C.DomainMatcher
Pool *fakeip.Pool
Hosts *trie.DomainTrie[resolver.HostValue]
Policy []Policy
@ -495,8 +495,8 @@ func NewResolver(config Config) *Resolver {
}
for _, policy := range config.Policy {
if policy.Rule != nil {
insertPolicy(domainRulePolicy{rule: policy.Rule, dnsClients: cacheTransform(policy.NameServers)})
if policy.Matcher != nil {
insertPolicy(domainMatcherPolicy{matcher: policy.Matcher, dnsClients: cacheTransform(policy.NameServers)})
} else {
if triePolicy == nil {
triePolicy = trie.New[[]dnsClient]()

View File

@ -3,6 +3,7 @@ package common
import (
"errors"
"fmt"
"net/netip"
"strings"
"github.com/metacubex/mihomo/component/geodata"
@ -11,6 +12,8 @@ import (
"github.com/metacubex/mihomo/component/resolver"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log"
"golang.org/x/exp/slices"
)
type GEOIP struct {
@ -41,52 +44,84 @@ func (g *GEOIP) Match(metadata *C.Metadata) (bool, string) {
}
if g.country == "lan" {
return ip.IsPrivate() ||
ip.IsUnspecified() ||
ip.IsLoopback() ||
ip.IsMulticast() ||
ip.IsLinkLocalUnicast() ||
resolver.IsFakeBroadcastIP(ip), g.adapter
return g.isLan(ip), g.adapter
}
for _, code := range metadata.DstGeoIP {
if g.country == code {
return true, g.adapter
}
}
if !C.GeodataMode {
if C.GeodataMode {
if g.isSourceIP {
codes := mmdb.IPInstance().LookupCode(ip.AsSlice())
for _, code := range codes {
if g.country == code {
return true, g.adapter
}
if slices.Contains(metadata.SrcGeoIP, g.country) {
return true, g.adapter
}
return false, g.adapter
}
if metadata.DstGeoIP != nil {
return false, g.adapter
}
metadata.DstGeoIP = mmdb.IPInstance().LookupCode(ip.AsSlice())
for _, code := range metadata.DstGeoIP {
if g.country == code {
} else {
if slices.Contains(metadata.DstGeoIP, g.country) {
return true, g.adapter
}
}
return false, g.adapter
matcher, err := g.getIPMatcher()
if err != nil {
return false, ""
}
match := matcher.Match(ip)
if match {
if g.isSourceIP {
metadata.SrcGeoIP = append(metadata.SrcGeoIP, g.country)
} else {
metadata.DstGeoIP = append(metadata.DstGeoIP, g.country)
}
}
return match, g.adapter
}
matcher, err := g.GetIPMatcher()
if err != nil {
return false, ""
if g.isSourceIP {
if metadata.SrcGeoIP != nil {
return slices.Contains(metadata.SrcGeoIP, g.country), g.adapter
}
} else {
if metadata.DstGeoIP != nil {
return slices.Contains(metadata.DstGeoIP, g.country), g.adapter
}
}
match := matcher.Match(ip)
if match && !g.isSourceIP {
metadata.DstGeoIP = append(metadata.DstGeoIP, g.country)
codes := mmdb.IPInstance().LookupCode(ip.AsSlice())
if g.isSourceIP {
metadata.SrcGeoIP = codes
} else {
metadata.DstGeoIP = codes
}
return match, g.adapter
if slices.Contains(codes, g.country) {
return true, g.adapter
}
return false, ""
}
// MatchIp implements C.IpMatcher
func (g *GEOIP) MatchIp(ip netip.Addr) bool {
if !ip.IsValid() {
return false
}
if g.country == "lan" {
return g.isLan(ip)
}
if C.GeodataMode {
matcher, err := g.getIPMatcher()
if err != nil {
return false
}
return matcher.Match(ip)
}
codes := mmdb.IPInstance().LookupCode(ip.AsSlice())
return slices.Contains(codes, g.country)
}
func (g *GEOIP) isLan(ip netip.Addr) bool {
return ip.IsPrivate() ||
ip.IsUnspecified() ||
ip.IsLoopback() ||
ip.IsMulticast() ||
ip.IsLinkLocalUnicast() ||
resolver.IsFakeBroadcastIP(ip)
}
func (g *GEOIP) Adapter() string {
@ -106,14 +141,19 @@ func (g *GEOIP) GetCountry() string {
}
func (g *GEOIP) GetIPMatcher() (router.IPMatcher, error) {
if g.geodata {
geoIPMatcher, err := geodata.LoadGeoIPMatcher(g.country)
if err != nil {
return nil, fmt.Errorf("[GeoIP] %w", err)
}
return geoIPMatcher, nil
if C.GeodataMode {
return g.getIPMatcher()
}
return nil, errors.New("geoip country not set")
return nil, errors.New("not geodata mode")
}
func (g *GEOIP) getIPMatcher() (router.IPMatcher, error) {
geoIPMatcher, err := geodata.LoadGeoIPMatcher(g.country)
if err != nil {
return nil, fmt.Errorf("[GeoIP] %w", err)
}
return geoIPMatcher, nil
}
func (g *GEOIP) GetRecodeSize() int {
@ -141,12 +181,13 @@ func NewGEOIP(country string, adapter string, isSrc, noResolveIP bool) (*GEOIP,
return geoip, nil
}
geoip.geodata = true
geoIPMatcher, err := geoip.GetIPMatcher() // test load
if err != nil {
return nil, err
if C.GeodataMode {
geoIPMatcher, err := geoip.getIPMatcher() // test load
if err != nil {
return nil, err
}
log.Infoln("Finished initial GeoIP rule %s => %s, records: %d", country, adapter, geoIPMatcher.Count())
}
log.Infoln("Finished initial GeoIP rule %s => %s, records: %d", country, adapter, geoIPMatcher.Count())
return geoip, nil
}

View File

@ -23,15 +23,19 @@ func (gs *GEOSITE) RuleType() C.RuleType {
}
func (gs *GEOSITE) Match(metadata *C.Metadata) (bool, string) {
domain := metadata.RuleHost()
return gs.MatchDomain(metadata.RuleHost()), gs.adapter
}
// MatchDomain implements C.DomainMatcher
func (gs *GEOSITE) MatchDomain(domain string) bool {
if len(domain) == 0 {
return false, ""
return false
}
matcher, err := gs.GetDomainMatcher()
if err != nil {
return false, ""
return false
}
return matcher.ApplyDomain(domain), gs.adapter
return matcher.ApplyDomain(domain)
}
func (gs *GEOSITE) Adapter() string {

View File

@ -28,8 +28,11 @@ func (a *ASN) Match(metadata *C.Metadata) (bool, string) {
result := mmdb.ASNInstance().LookupASN(ip.AsSlice())
asnNumber := strconv.FormatUint(uint64(result.AutonomousSystemNumber), 10)
if !a.isSourceIP {
metadata.DstIPASN = asnNumber + " " + result.AutonomousSystemOrganization
ipASN := asnNumber + " " + result.AutonomousSystemOrganization
if a.isSourceIP {
metadata.SrcIPASN = ipASN
} else {
metadata.DstIPASN = ipASN
}
match := a.asn == asnNumber

View File

@ -1,40 +0,0 @@
package provider
import (
"github.com/metacubex/mihomo/component/trie"
C "github.com/metacubex/mihomo/constant"
)
type DomainSet struct {
*domainStrategy
adapter string
}
func (d *DomainSet) ProviderNames() []string {
return nil
}
func (d *DomainSet) RuleType() C.RuleType {
return C.DomainSet
}
func (d *DomainSet) Match(metadata *C.Metadata) (bool, string) {
return d.domainStrategy.Match(metadata), d.adapter
}
func (d *DomainSet) Adapter() string {
return d.adapter
}
func (d *DomainSet) Payload() string {
return ""
}
func NewDomainSet(domainSet *trie.DomainSet, adapter string) *DomainSet {
return &DomainSet{
domainStrategy: &domainStrategy{domainSet: domainSet},
adapter: adapter,
}
}
var _ C.Rule = (*DomainSet)(nil)

View File

@ -1,40 +0,0 @@
package provider
import (
"github.com/metacubex/mihomo/component/cidr"
C "github.com/metacubex/mihomo/constant"
)
type IpCidrSet struct {
*ipcidrStrategy
adapter string
}
func (d *IpCidrSet) ProviderNames() []string {
return nil
}
func (d *IpCidrSet) RuleType() C.RuleType {
return C.IpCidrSet
}
func (d *IpCidrSet) Match(metadata *C.Metadata) (bool, string) {
return d.ipcidrStrategy.Match(metadata), d.adapter
}
func (d *IpCidrSet) Adapter() string {
return d.adapter
}
func (d *IpCidrSet) Payload() string {
return ""
}
func NewIpCidrSet(cidrSet *cidr.IpCidrSet, adapter string) *IpCidrSet {
return &IpCidrSet{
ipcidrStrategy: &ipcidrStrategy{cidrSet: cidrSet},
adapter: adapter,
}
}
var _ C.Rule = (*IpCidrSet)(nil)

View File

@ -1,6 +1,8 @@
package provider
import (
"net/netip"
C "github.com/metacubex/mihomo/constant"
P "github.com/metacubex/mihomo/constant/provider"
"github.com/metacubex/mihomo/rules/common"
@ -35,6 +37,18 @@ func (rs *RuleSet) Match(metadata *C.Metadata) (bool, string) {
return false, ""
}
// MatchDomain implements C.DomainMatcher
func (rs *RuleSet) MatchDomain(domain string) bool {
ok, _ := rs.Match(&C.Metadata{Host: domain})
return ok
}
// MatchIp implements C.IpMatcher
func (rs *RuleSet) MatchIp(ip netip.Addr) bool {
ok, _ := rs.Match(&C.Metadata{DstIP: ip})
return ok
}
func (rs *RuleSet) Adapter() string {
return rs.adapter
}