diff --git a/app/dispatcher/default.go b/app/dispatcher/default.go index 6823884ec..1531866f4 100644 --- a/app/dispatcher/default.go +++ b/app/dispatcher/default.go @@ -260,12 +260,7 @@ func sniffer(ctx context.Context, cReader *cachedReader) (SniffResult, error) { func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) { var handler outbound.Handler - skipRoutePick := false - if content := session.ContentFromContext(ctx); content != nil { - skipRoutePick = content.SkipRoutePick - } - - if d.router != nil && !skipRoutePick { + if d.router != nil { if route, err := d.router.PickRoute(routing_session.AsRoutingContext(ctx)); err == nil { tag := route.GetOutboundTag() if h := d.ohm.GetHandler(tag); h != nil { diff --git a/app/dns/nameserver_doh.go b/app/dns/nameserver_doh.go index 2dfdba183..b458be6f2 100644 --- a/app/dns/nameserver_doh.go +++ b/app/dns/nameserver_doh.go @@ -230,8 +230,8 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP n } dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{ - Protocol: "https", - SkipRoutePick: true, + Protocol: "https", + SkipDNSResolve: true, }) // forced to use mux for DOH diff --git a/app/dns/nameserver_quic.go b/app/dns/nameserver_quic.go index 48f3632b1..3001c231f 100644 --- a/app/dns/nameserver_quic.go +++ b/app/dns/nameserver_quic.go @@ -176,8 +176,8 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP } dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{ - Protocol: "quic", - SkipRoutePick: true, + Protocol: "quic", + SkipDNSResolve: true, }) var cancel context.CancelFunc diff --git a/app/router/command/config.go b/app/router/command/config.go index 1385f296f..c6a242e6c 100644 --- a/app/router/command/config.go +++ b/app/router/command/config.go @@ -28,6 +28,13 @@ func (c routingContext) GetTargetPort() net.Port { return net.Port(c.RoutingContext.GetTargetPort()) } +// GetSkipDNSResolve is a mock implementation here to match the interface, +// SkipDNSResolve is set from dns module, no use if coming from a protobuf object? +// TODO: please confirm @Vigilans +func (c routingContext) GetSkipDNSResolve() bool { + return false +} + // AsRoutingContext converts a protobuf RoutingContext into an implementation of routing.Context. func AsRoutingContext(r *RoutingContext) routing.Context { return routingContext{r} diff --git a/app/router/router.go b/app/router/router.go index 30cfe6592..e933a045c 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -82,7 +82,13 @@ func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) { } func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) { - if r.domainStrategy == Config_IpOnDemand { + + // SkipDNSResolve is set from DNS module. + // the DOH remote server maybe a domain name, + // this prevents cycle resolving dead loop + skipDNSResolve := ctx.GetSkipDNSResolve() + + if r.domainStrategy == Config_IpOnDemand && !skipDNSResolve { ctx = routing_dns.ContextWithDNSClient(ctx, r.dns) } @@ -92,7 +98,7 @@ func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, } } - if r.domainStrategy != Config_IpIfNonMatch || len(ctx.GetTargetDomain()) == 0 { + if r.domainStrategy != Config_IpIfNonMatch || len(ctx.GetTargetDomain()) == 0 || skipDNSResolve { return nil, ctx, common.ErrNoClue } diff --git a/common/session/session.go b/common/session/session.go index 17b461d56..463ebac80 100644 --- a/common/session/session.go +++ b/common/session/session.go @@ -68,7 +68,7 @@ type Content struct { Attributes map[string]string - SkipRoutePick bool + SkipDNSResolve bool } // Sockopt is the settings for socket connection. diff --git a/features/routing/context.go b/features/routing/context.go index 8fea19150..9a7e8b375 100644 --- a/features/routing/context.go +++ b/features/routing/context.go @@ -37,4 +37,7 @@ type Context interface { // GetAttributes returns extra attributes from the conneciont content. GetAttributes() map[string]string + + // GetSkipDNSResolve returns a flag switch for weather skip dns resolve during route pick. + GetSkipDNSResolve() bool } diff --git a/features/routing/session/context.go b/features/routing/session/context.go index bd5bb6337..a7a32f18d 100644 --- a/features/routing/session/context.go +++ b/features/routing/session/context.go @@ -109,6 +109,14 @@ func (ctx *Context) GetAttributes() map[string]string { return ctx.Content.Attributes } +// GetSkipDNSResolve implements routing.Context. +func (ctx *Context) GetSkipDNSResolve() bool { + if ctx.Content == nil { + return false + } + return ctx.Content.SkipDNSResolve +} + // AsRoutingContext creates a context from context.context with session info. func AsRoutingContext(ctx context.Context) routing.Context { return &Context{