diff --git a/config/dns_policy_rule.go b/config/dns_policy_rule.go index ba3be5e3..ff73d0d2 100644 --- a/config/dns_policy_rule.go +++ b/config/dns_policy_rule.go @@ -24,22 +24,38 @@ type ruleMatcher struct { func (r *ruleMatcher) MatchDomain(domain string) bool { typ, found := cache.Get(domain) if !found { - p, _, err := tunnel.ResolveMetadata( - &C.Metadata{ - NetWork: C.TCP, - Type: C.INNER, // avoid process lookup - Host: domain, - DstIP: netip.AddrFrom4([4]byte{}), // avoid dns lookup - }, - ) + meta := &C.Metadata{ + NetWork: C.TCP, + Type: C.INNER, // avoid process lookup + Host: domain, + DstIP: netip.AddrFrom4([4]byte{}), // avoid dns lookup + } + p, _, err := tunnel.ResolveMetadata(meta) if err != nil { log.Warnln("[DNS] ruleMatcher: match(%s) got err %v", domain, err.Error()) return false } - log.Debugln("[DNS] ruleMatcher: match(%s) -> %s", domain, p.Type().String()) - cache.Set(domain, p.Type()) - typ = p.Type() + // parse multi-layer nesting + adapter := p + for { + next := adapter.Unwrap(meta, false) + if next != nil { + adapter = next + } else { + break + } + } + typ = adapter.Type() + cache.Set(domain, typ) } + ret := ruleMatch(typ, r) + log.Debugln("[DNS] ruleMatcher: domain(%s, %s) rule(%s), match: %v", + domain, typ.String(), r.typ, ret) + + return ret +} + +func ruleMatch(typ C.AdapterType, r *ruleMatcher) bool { switch typ { case C.Direct, C.Compatible: if r.typ == "direct" {