Browse Source

DNS: refine skipRoutePick (#558)

V2Fly Team 4 years ago
parent
commit
66e203f156

+ 1 - 6
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 {

+ 2 - 2
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

+ 2 - 2
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

+ 7 - 0
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}

+ 8 - 2
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
 	}
 

+ 1 - 1
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.

+ 3 - 0
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
 }

+ 8 - 0
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{